﻿using System.IO;
using System.Linq;
using DotNet.DevOps.Tasks.Util;
using Ionic.Zip;

namespace DotNet.DevOps.Tasks.Service.Helpers
{
    internal class FileManager
    {
        private ILog Log { get; set; }
        private string Identifier { get; set; }

        public FileManager(ILog log, string identifier)
        {
            Identifier = identifier;
            Log = log;
        }

        public bool CheckFileExists(string path, string file)
        {
            if (ZipFile.IsZipFile(path))
            {
                var zip = new ZipFile(path);
                if (zip.Any(entry => entry.FileName == file))
                {
                    return true;
                }
            }
            else
            {
                if (new DirectoryInfo(path).GetFiles(file).Count() > 0)
                {
                    return true;
                }
            }
            return false;
        }

        public void Copy(string source, string destination)
        {
            if(ZipFile.IsZipFile(source))
            {
                Log.LogInfo(string.Format("{0} - Unzipping {1} -> {2}", Identifier, source, destination));
                Unzip(source, destination);
            }
            else
            {
                Log.LogInfo(string.Format("{0} - Copying files {1} -> {2}", Identifier, source, destination));
                CopyAll(new DirectoryInfo(source), new DirectoryInfo(destination));
            }
        }

        private void CopyAll(DirectoryInfo source, DirectoryInfo destination)
        {
            if (Directory.Exists(destination.FullName) == false)
            {
                Log.LogInfo(string.Format("{0} - Creating: {1}", Identifier, destination.FullName));
                Directory.CreateDirectory(destination.FullName);
            }

            // Copy each file into it’s new directory.
            foreach (var file in source.GetFiles())
            {
                var fileDestination = Path.Combine(destination.ToString(), file.Name);

                Log.LogInfo(string.Format("{0} - Copying file {1}", Identifier, file));

                file.CopyTo(fileDestination, true);
            }

            var dirs = source.GetDirectories().Where(dir => dir.FullName != destination.FullName);
            // Copy each subdirectory using recursion.
            foreach (var diSourceSubDir in dirs)
            {
                var nextTargetSubDir = destination.CreateSubdirectory(diSourceSubDir.Name);
                CopyAll(diSourceSubDir, nextTargetSubDir);
            }
        }

        private void Unzip(string zipFilePath, string destination)
        {
            using (var zip = new ZipFile(zipFilePath))
            {
                zip.ExtractProgress += OnExtractProgress;
                zip.ExtractAll(destination, ExtractExistingFileAction.OverwriteSilently);
            }

            Log.LogInfo(string.Format("{0} - Unzip success: {1} -> {2}", Identifier, zipFilePath, destination));
        }

        private void OnExtractProgress(object sender, ExtractProgressEventArgs e)
        {
            if (e == null || e.CurrentEntry == null)
                return;

            if (e.EventType == ZipProgressEventType.Extracting_AfterExtractEntry)
            {
                Log.LogInfo(string.Format("{0} - Unzipped: {1}", Identifier, e.CurrentEntry.FileName));
            }
        }
    }
}
